import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Betting } from './entities/betting.entity';
import { CreateBettingDto } from './dto/create-betting.dto';
import { UpdateBettingDto } from './dto/update-betting.dto';

/**
 * 投注服务类
 */
@Injectable()
export class BettingService {
  constructor(
    @InjectRepository(Betting)
    private readonly bettingRepository: Repository<Betting>,
  ) {}

  /**
   * 创建投注选项
   */
  async create(createBettingDto: CreateBettingDto): Promise<Betting> {
    const betting = this.bettingRepository.create(createBettingDto);
    return await this.bettingRepository.save(betting);
  }

  /**
   * 更新投注选项
   */
  async update(id: number, updateBettingDto: UpdateBettingDto): Promise<Betting> {
    await this.bettingRepository.update(id, updateBettingDto);
    const betting = await this.bettingRepository.findOne({ where: { id } });
    if (!betting) {
      throw new Error(`投注选项不存在，ID: ${id}`);
    }
    return betting;
  }

  /**
   * 根据比赛ID获取投注选项
   */
  async findByMatchId(matchId: number): Promise<Betting[]> {
    return await this.bettingRepository.find({
      where: { matchId },
      order: { id: 'ASC' }
    });
  }

  /**
   * 更新比赛结果并计算预测命中
   * @param matchId 比赛ID
   * @param homeScore 主队比分
   * @param awayScore 客队比分
   */
  async updateMatchResult(matchId: number, homeScore: number, awayScore: number): Promise<void> {
    // 计算比赛结果
    let matchResult: string;
    if (homeScore > awayScore) {
      matchResult = 'win';
    } else if (homeScore === awayScore) {
      matchResult = 'draw';
    } else {
      matchResult = 'lose';
    }

    // 获取该比赛的所有投注选项
    const bettings = await this.findByMatchId(matchId);

    // 更新每个投注选项的比分、结果和预测命中状态
    for (const betting of bettings) {
      const predictionHit = this.calculatePredictionHit(betting.recommendedResult, matchResult);
      
      await this.bettingRepository.update(betting.id, {
        homeScore,
        awayScore,
        matchResult,
        predictionHit,
      });
    }
  }

  /**
   * 计算预测是否命中
   * @param recommendedResult 推荐结果数组
   * @param actualResult 实际比赛结果
   * @returns 是否命中
   */
  private calculatePredictionHit(recommendedResult: string[], actualResult: string): boolean {
    if (!recommendedResult || recommendedResult.length === 0) {
      return false; // 没有推荐结果，视为未命中
    }
    
    return recommendedResult.includes(actualResult);
  }

  /**
   * 批量更新推荐结果
   * @param bettingId 投注ID
   * @param recommendedResult 推荐结果
   */
  async updateRecommendedResult(bettingId: number, recommendedResult: string[]): Promise<Betting> {
    
    // 参数验证
    // if (recommendedResult === undefined || recommendedResult === null) {
    //   throw new Error('推荐结果不能为空');
    // }
    
    if (!Array.isArray(recommendedResult)) {
      throw new Error('推荐结果必须是数组格式');
    }
    
    // if (recommendedResult.length === 0) {
    //   throw new Error('推荐结果数组不能为空');
    // }
    
    // 验证数组元素
    const validResults = ['win', 'draw', 'lose'];
    for (const result of recommendedResult) {
      if (!validResults.includes(result)) {
        throw new Error(`无效的推荐结果: ${result}，只能是 win、draw 或 lose`);
      }
    }
    
    // 先检查投注是否存在
    const existingBetting = await this.bettingRepository.findOne({ where: { id: bettingId } });
    if (!existingBetting) {
      throw new Error(`投注选项不存在，ID: ${bettingId}`);
    }
    
    console.log('更新前的推荐结果:', existingBetting.recommendedResult);
    
    // 执行更新
    const updateResult = await this.bettingRepository.update(bettingId, { recommendedResult });
    console.log('数据库更新结果:', updateResult);
    
    // 重新查询更新后的数据
    const updatedBetting = await this.bettingRepository.findOne({ where: { id: bettingId } });
    console.log('更新后的推荐结果:', updatedBetting?.recommendedResult);
    
    if (!updatedBetting) {
      throw new Error(`更新后无法找到投注选项，ID: ${bettingId}`);
    }
    
    return updatedBetting;
  }

  /**
   * 获取投注统计信息
   * @param matchId 比赛ID（可选）
   */
  async getStatistics(matchId?: number) {
    const queryBuilder = this.bettingRepository.createQueryBuilder('betting');
    
    if (matchId) {
      queryBuilder.where('betting.matchId = :matchId', { matchId });
    }

    const [total, hitCount, missCount] = await Promise.all([
      queryBuilder.getCount(),
      queryBuilder.clone().andWhere('betting.predictionHit = :hit', { hit: true }).getCount(),
      queryBuilder.clone().andWhere('betting.predictionHit = :hit', { hit: false }).getCount(),
    ]);

    const hitRate = total > 0 ? (hitCount / total * 100).toFixed(2) : '0.00';

    return {
      total,
      hitCount,
      missCount,
      hitRate: `${hitRate}%`,
    };
  }
}